#ifndef SCENE_H
#define SCENE_H

#include "Camera.cu"
#include "GeometryList.cu"
#include "Triangle.cu"
#include "Vertex.cu"
#include "Geometry.cu"
#include "Model.cu"
#include "Instance.cu"
#include "Mesh.cu"
#include "global_object.h"

using namespace std;
class Scene : public DeviceObject
{
public:
	Camera* camera;
	Model** models;
	int modelCt;
	Instance** instances;
	int instanceCt;

	inline __host__ __device__  static Scene* getTestScene(){

		Scene* scn = new Scene();
		scn->models = new Model* [1];
		scn->camera = new Camera();
		scn->camera->origin = Vector3(0.0f, 0.0f, 3.0f);
		scn->camera->gaze = Vector3(0.0f, 0.0f, -1.0f);
		scn->camera->planeWidth = 1.0f;
		scn->camera->focalLength = 0.5f;
		scn->camera->buildBasis();
		

		Vertex *vert1, *vert2, *vert3;
		vert1 = new Vertex(Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f));
		vert2 = new Vertex(Vector3(1.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f));
		vert3 = new Vertex(Vector3(0.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f));

		Triangle* t = new Triangle(vert1, vert2, vert3);
		Model* triangle_model = new Model();
		triangle_model->geometry = t;
		Material* mtl = new Material();
		mtl->diffuse = Vector3(0.5f, 0.3f, 0.8f);
		triangle_model->material = mtl;
		triangle_model->texture = new Texture();
		scn->models[0] = triangle_model;
		scn->modelCt = 1;
		scn->instanceCt = 0;
	
		return scn;

	}

	inline __host__ __device__  Scene(void){
		this->size = sizeof(Scene);
	}

	inline __host__ __device__  ~Scene(void);

	inline __host__ void copyToDevice() {
		Scene d = Scene(*this);

		if(camera->d_address == NULL){
			camera->copyToDevice();
		}
		d.camera = (Camera*)camera->d_address;
		
		for(int i=0; i<modelCt; i++){
			if(models[i]->d_address == NULL){
				models[i]->copyToDevice();
			}
			d.models[i] = (Model*)models[i]->d_address;
		}
		cudaMemcpy(d.models, models, sizeof(Model)*modelCt, cudaMemcpyHostToDevice); 
		//copy over array of model pointers

		for(int i=0; i<instanceCt; i++){
			if(instances[i]->d_address == NULL){
				instances[i]->copyToDevice();
			}
			d.instances[i] = (Instance*)instances[i]->d_address;
		}
		//copy over array of instance pointers

		cudaMemcpy(d.instances, instances, sizeof(Instance)*instanceCt, cudaMemcpyHostToDevice); 
		cudaMemcpy(d_address, &d, sizeof(Scene), cudaMemcpyHostToDevice);
	}

};

#endif
